#!/usr/bin/env perl

 # required modules
 use Net::FTP;

if ($#ARGV+1 != 3) {
	die "Usage: ftplist.pl host username password\n";
}
my $host = $ARGV[0];
my $user = $ARGV[1];
my $passwd = $ARGV[2];
my $ftp; 

sub parse_files {
    my(@to_return) = ();
    foreach my $line (@_) {

        next unless $line =~ /^
                                                              (\S+)\s+             #permissions
                                                                \d+\s+              #link count
                                                                \S+\s+              #user owner
                                                                \S+\s+              #group owner
                                                                (\d+)\s+              #size
                                                                (\w+\s+\w+\s+\S+)\s+  #last modification date
                                                                (.+?)\s*            #filename
                                                                (?:->\s*(.+))?      #optional link part
                                                              $
                                                            /x;

        my($perms, $size, $time, $filename, $linkname) = ($1, $2, $3, $4, $5);

        next if $filename =~ /^\.{1,2}$/;

        my $file;
        if ($perms =~/^-/){
            $file = Net::FTP::File->new( plainfile => 1,
                                         filename  => $filename, 
                                         filesize => $size,
                                         modtime => $time);
        }
        elsif ($perms =~ /^d/) {
            $file = Net::FTP::File->new( directory => 1,
                                                    filename  => $filename );
        } elsif ($perms =~/^l/) {
            $file = Net::FTP::File->new( 'symlink' => 1,
                                                    filename  => $filename,
                                                    linkname  => $linkname );
        } else {
            next; #didn't match, skip the file
        }

        push(@to_return, $file);
    }

    return(@to_return);
}


 sub printRecursiveDirListing
  {
      # directory parameter passed to the sub-routine
      my $dir = $_[0];
  
      # if the directory was passed onto the sub-routin, change the remote directory
      $ftp->cwd($dir) if($dir);
  
      # the current working directory on the remote server
      my $cur_dir = $ftp->pwd();

#      print ("Comparing $dir vs $cur_dir\n");
      return if ($dir ne $cur_dir);

      # get the file listing
      @ls = $ftp->ls('-l');
  
      # parse and loop through the directory listing
      my @parsed=parse_files(@ls);

      undef @ls;

      my @dirs;

      while (my $file = pop(@parsed))
      {
	next if $file->is_symlink();

        my $name=$file->filename();
	if ($file->is_directory())
	{
		if ($cur_dir eq '/') {
        	  push(@dirs,"/$name");
		} else {
        	  push(@dirs,"$cur_dir/$name");
		}
	  next;
	}

        $size=$file->filesize();
        $mtime=$file->modtime();  

	if ($curdir eq '/')
	{
		print "/$name|$size|$mtime\n";
	}
	else
	{
		print "$cur_dir/$name|$size|$mtime\n";
	}

      }

      while (my $name = pop(@dirs))
      {
          # recursive call to get the entries in the entry, and get an array of return values
#print("Scanning directory $name\n");
          printRecursiveDirListing ("$name");
  
      }
  }

# create a new instance of the FTP connection
$ftp = Net::FTP->new($host, Debug=>0) or die("Cannot connect $!");
# login to the server
$ftp->login($user,$passwd) or die("Login failed $!");  
  
printRecursiveDirListing ("/");

# close the FTP connection
$ftp->quit();

#use Net::FTP::Recursive::File;
#use Net::FTP::Recursive;
#use FileHandle;
#$fh=new FileHandle();
#$fh->open(">ftplist.txt");
#$ftp = Net::FTP::Recursive->new($host);
#$ftp->login($user,$passwd);
#$ftp->rdir(Filehandle=>$fh);
#$ftp->quit();
  
package Net::FTP::File;

use vars qw/@ISA/;
use Carp;

@ISA = ();

sub new{
    my $pkg = shift;

    my $self = { plainfile => 0,
                 directory => 0,
                 'symlink' => 0,
                 @_
               };

    croak 'Must set a filename when creating a File object!'
      unless defined $self->{filename};

    if( $self->{'symlink'} and not $self->{linkname} ){
        croak 'Must set a linkname when creating a File object for a symlink!';
    }

    bless $self, $pkg;
}

sub linkname{
    return $_[0]->{linkname};
}

sub filename{
    return $_[0]->{filename};
}

sub filesize{
    return $_[0]->{filesize};
}

sub modtime{
    return $_[0]->{modtime};
}

sub is_symlink{
    return $_[0]->{symlink};
}

sub is_directory{
    return $_[0]->{directory};
}

sub is_plainfile{
    return $_[0]->{plainfile};
}

